<!DOCTYPE html>

<html lang="en">
  <head>
    <title>Editor | Heartex</title>
    <link href="https://app.heartex.ai/static/css/main.css" rel="stylesheet" />
    <script src="https://app.heartex.ai/static/js/jquery.min.js"></script>

    <!-- Editor CSS -->

    <link
      href="https://app.heartex.ai/playground/css/main.css"
      rel="stylesheet"
    />

    <!-- Editor JS -->

    <script src="https://app.heartex.ai/playground/js/main.js"></script>
    <script src="https://app.heartex.ai/static/sdk/htx-docker-init-v1.0.0.js"></script>

    <style>
      body,
      html {
        background: none !important;
      }

      body::-webkit-scrollbar-track {
        -webkit-box-shadow: inset 0 0 2px rgba(178, 178, 178, 0.3) !important;
        background-color: #f5f5f5 !important;
      }

      body::-webkit-scrollbar {
        width: 2px !important;
        height: 2px !important;
        background-color: #f5f5f5 !important;
      }

      body::-webkit-scrollbar-thumb {
        background-color: #c3c3c3 !important;
        border: 2px solid #b4b4b4 !important;
      }

      #label-studio div[class^="App_editor"],
      div[class*="App_editor"] {
        width: 95% !important;
        min-width: 95% !important;
        max-width: 95% !important;
      }
      #label-studio .ls-segment {
        top: 0;
      }
    </style>
  </head>
  <body>
    <div id="label-studio">
      <div class="ui loader active inline centered"></div>
    </div>

    <script id="task-data" type="application/json">
      {
        "id": 6077,
        "data": {
          "image": "https://app.heartex.ai/static/samples/sample.jpg",
          "text": "To have faith is to trust yourself to the water"
        },
        "completions": null,
        "predictions": null,
        "project": 1,
        "accuracy": 0,
        "created_at": "2024-03-10T02:46:32.000000Z",
        "updated_at": "2024-03-10T02:46:32.000000Z"
      }
    </script>
    <div class="output-col">
      <h4>Output preview</h4>
      <pre class="preview" id="data-results">[]</pre>
    </div>

    <script>
      (function (factory) {
        var registeredInModuleLoader = false;
        if (typeof define === "function" && define.amd) {
          define(factory);
          registeredInModuleLoader = true;
        }
        if (typeof exports === "object") {
          module.exports = factory();
          registeredInModuleLoader = true;
        }
        if (!registeredInModuleLoader) {
          var OldCookies = window.Cookies;
          var api = (window.Cookies = factory());
          api.noConflict = function () {
            window.Cookies = OldCookies;
            return api;
          };
        }
      })(function () {
        window.USE_DRAFTS = false;

        // New Label Studio instance with integrated task data
        var Htx = new HeartexSDK({
          elid: "label-studio",
          config: `
            <View>
              <!-- Image with Polygons -->
              <View style="padding: 25px;
                          box-shadow: 2px 2px 8px #AAA">
                <Header value="Label the image with polygons"/>
                <Image name="img" value="$image"/>
                <Text name="text1"
                      value="Select label, start to click on image"/>

                <PolygonLabels name="tag" toName="img">
                  <Label value="Airbus" background="blue"/>
                  <Label value="Boeing" background="red"/>
                </PolygonLabels>
              </View>
            </View>
            `,
          user: { pk: 1, firstName: "Awesome", lastName: "User" },
          project: 1,
          options: { secureMode: false },
          interfaces: [
            "basic",
            "panel", // undo, redo, reset panel
            "side-column", // entity
          ],
        });

        Htx.showTask(
          JSON.parse(document.getElementById("task-data").textContent),
          { addInitial: true, loadCompletionIfExists: true }
        );
        function extend() {
          var i = 0;
          var result = {};
          for (; i < arguments.length; i++) {
            var attributes = arguments[i];
            for (var key in attributes) {
              result[key] = attributes[key];
            }
          }
          return result;
        }

        function init(converter) {
          function api(key, value, attributes) {
            var result;
            if (typeof document === "undefined") {
              return;
            }

            // Write

            if (arguments.length > 1) {
              attributes = extend(
                {
                  path: "/",
                },
                api.defaults,
                attributes
              );

              if (typeof attributes.expires === "number") {
                var expires = new Date();
                expires.setMilliseconds(
                  expires.getMilliseconds() + attributes.expires * 864e5
                );
                attributes.expires = expires;
              }

              // We're using "expires" because "max-age" is not supported by IE
              attributes.expires = attributes.expires
                ? attributes.expires.toUTCString()
                : "";

              try {
                result = JSON.stringify(value);
                if (/^[\{\[]/.test(result)) {
                  value = result;
                }
              } catch (e) {}

              if (!converter.write) {
                value = encodeURIComponent(String(value)).replace(
                  /%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,
                  decodeURIComponent
                );
              } else {
                value = converter.write(value, key);
              }

              key = encodeURIComponent(String(key));
              key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
              key = key.replace(/[\(\)]/g, escape);

              var stringifiedAttributes = "";

              for (var attributeName in attributes) {
                if (!attributes[attributeName]) {
                  continue;
                }
                stringifiedAttributes += "; " + attributeName;
                if (attributes[attributeName] === true) {
                  continue;
                }
                stringifiedAttributes += "=" + attributes[attributeName];
              }
              return (document.cookie =
                key + "=" + value + stringifiedAttributes);
            }

            // Read

            if (!key) {
              result = {};
            }

            // To prevent the for loop in the first place assign an empty array
            // in case there are no cookies at all. Also prevents odd result when
            // calling "get()"
            var cookies = document.cookie ? document.cookie.split("; ") : [];
            var rdecode = /(%[0-9A-Z]{2})+/g;
            var i = 0;

            for (; i < cookies.length; i++) {
              var parts = cookies[i].split("=");
              var cookie = parts.slice(1).join("=");

              if (!this.json && cookie.charAt(0) === '"') {
                cookie = cookie.slice(1, -1);
              }

              try {
                var name = parts[0].replace(rdecode, decodeURIComponent);
                cookie = converter.read
                  ? converter.read(cookie, name)
                  : converter(cookie, name) ||
                    cookie.replace(rdecode, decodeURIComponent);

                if (this.json) {
                  try {
                    cookie = JSON.parse(cookie);
                  } catch (e) {}
                }

                if (key === name) {
                  result = cookie;
                  break;
                }

                if (!key) {
                  result[name] = cookie;
                }
              } catch (e) {}
            }

            return result;
          }

          api.set = api;
          api.get = function (key, default_value) {
            var value = api.call(api, key);
            return value === undefined ? default_value : value;
          };
          api.getJSON = function () {
            return api.apply(
              {
                json: true,
              },
              [].slice.call(arguments)
            );
          };
          api.defaults = {};

          api.remove = function (key, attributes) {
            api(
              key,
              "",
              extend(attributes, {
                expires: -1,
              })
            );
          };

          api.withConverter = init;

          return api;
        }

        return init(function () {});
      });

      // copy to clipboard
      var copyToClipboard = function (str) {
        var el = document.createElement("textarea"); // Create a <textarea> element
        el.value = str; // Set its value to the string that you want copied
        el.setAttribute("readonly", ""); // Make it readonly to be tamper-proof
        el.style.position = "absolute";
        el.style.left = "-9999px"; // Move outside the screen to make it invisible
        document.body.appendChild(el); // Append the <textarea> element to the HTML document
        var selected =
          document.getSelection().rangeCount > 0 // Check if there is any content selected previously
            ? document.getSelection().getRangeAt(0) // Store selection if found
            : false; // Mark as false to know no selection existed before
        el.select(); // Select the <textarea> content
        document.execCommand("copy"); // Copy - only works as a result of a user action (e.g. click events)
        document.body.removeChild(el); // Remove the <textarea> element
        if (selected) {
          // If a selection existed before copying
          document.getSelection().removeAllRanges(); // Unselect everything on the HTML document
          document.getSelection().addRange(selected); // Restore the original selection
        }
      };

      function uuidv4() {
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
          /[xy]/g,
          function (c) {
            var r = (Math.random() * 16) | 0,
              v = c == "x" ? r : (r & 0x3) | 0x8;
            return v.toString(16);
          }
        );
      }

      var confirm_already_shown = true;
      var edit_count = 0;
      var current_template_name = "start";
      var current_template_category = "start";
      var page_hash = uuidv4();
      var user_hash = Cookies.get("user_hash");
      if (user_hash === "null" || !user_hash) {
        user_hash = uuidv4();
        Cookies.set("user_hash", user_hash);
      }
      var lookup = {};

      $.ajax({
        url: "https://extreme-ip-lookup.com/json/",
        success: function (o) {
          lookup = o;
        },
        async: false,
      });

      $(function () {
        function addTemplateConfig($el) {
          var template_pk = $el.data("value");
          var value = $('[data-template-pk="' + template_pk + '"]').html();

          // extract readme from config
          var starter = "<!-- readme",
            terminator = "-->";
          var start = value.indexOf(starter);
          if (start >= 0) {
            var body_length =
              value.indexOf(terminator, start) - start - starter.length;
            var readme = value.substr(start + starter.length, body_length);

            // find first XML tag (<View> as usual) and start from it
            value = value.slice(
              value.indexOf(
                "<",
                start + starter.length + body_length + terminator.length
              )
            );
          }

          labelEditor.setValue(value);
          first_render = true;
        }

        $(".use-template").on("click", function () {
          var $el = $(this);
          edit_count = 0;
          current_template_name = $el.text();
          current_template_category = $(
            $el.parent().parent().find("i")[0]
          ).attr("title");

          if (labelEditor.getValue() !== "" && !confirm_already_shown) {
            var dialog = $("#confirm-config-template-dialog");
            dialog
              .modal({
                closable: true,
                keyboardShortcuts: true,
                onApprove: function () {
                  addTemplateConfig($el);
                },
              })
              .modal("show");

            // close on enter, unfortunately keyboardShortcuts doesn't work
            dialog.on("keypress", function () {
              if (event.keyCode === 13) {
                dialog.modal("hide");
                addTemplateConfig($el);
              }
            });

            confirm_already_shown = true;
          } else {
            addTemplateConfig($el);
          }

          return false;
        });

        var iframeTimer = null;

        function debounce(func, wait, immediate) {
          let timeout;

          return function () {
            const context = this,
              args = arguments;
            const later = () => {
              timeout = null;
              if (!immediate) func.apply(context, args);
            };
            const callNow = immediate && !timeout;

            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
          };
        }

        var prev_completion = null;

        // serialize editor output by timer
        setInterval(function () {
          if (typeof Htx !== "undefined") {
            var completion = JSON.stringify(
              Htx.completionStore.selected.serializeCompletion(),
              null,
              4
            );
            if (prev_completion !== completion) {
              if (completion.length > 3000) {
                completion = completion.slice(0, 3000) + " ...";
              }
              $("#data-results").text(completion);
              prev_completion = completion;
            }
          }
        }, 500);
      });
    </script>
  </body>
</html>
